[Perf][SM70] Add opt-in native-g32 AWQ QPN M1 dispatch - #521
yangzhuxinyzx merged 9 commits into
Conversation
Reuse the existing active-stage operator for TP4 g32 M2-8 decode, align warmup admission, and annotate scratch mutations. Keep C1 and unmatched contracts on existing routes; add focused coverage without new public operators or GEMM kernels. Validated with 51 GPU-directed tests, 32 dynamic-route operator comparisons, and QSA-fixed matched model runs. Single-run pure-decode gains: C4x64K +5.62%, C8x16K +2.24%. Natural-EOS AWQ outputs match 17/18; the retained and/+ near-tie and W13 rounding differences are not claimed bitwise exact. No precision-default changes or deployment. Co-authored-by: OpenAI Codex Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Separate implementation-only and existing-autotune gains; document EOS rounding limitations, capacity and startup observations, rollback, and the dual-format C1 follow-up. Co-authored-by: OpenAI Codex Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Record the new main integration gate separately from frozen GPU results; keep prefill and grouped decode admission disjoint. Co-authored-by: OpenAI Codex Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Co-authored-by: OpenAI Codex Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Assisted-by: OpenAI Codex Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Use the retained engine log instead of extrapolating cache block count. No production or benchmark changes. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Add the typed inference operator, prepared-bank decoder, FP32 reduction kernels and standalone GPU tests without changing model dispatch. Keep 3B scalar loading here so cooperative metadata access can be reviewed separately. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com> (cherry picked from commit 27a27d3) (cherry picked from commit 5b4135f)
Gate the native operator to the existing Qwen3.8 TP4 E512 M1 contract, retaining default-off behavior and neighboring routes. Document numerical attribution, observed quality changes, and incomplete production acceptance. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com> (cherry picked from commit 37fb5d2)
Evaluate both AWQ arithmetic paths against an independent fixed-weight reference; distinguish existing quantization error, local arithmetic bounds, and task-level quality. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com> (cherry picked from commit 6f73eac)
Fresh QPN runtime OFF/ON regression (2026-09-06 UTC)Reviewed #521 head The later #522 default-switch commit The only intended configuration change is Matched contract: 4 x V100 32GB / TP4, FP16 activation/KV, MTP0, frozen AWQ
These are engine-output all-active serving-decode rates, including the Quality and numerical evidenceAcross 65 frozen quality records, all per-record task scores were unchanged; An already-incorrect MBPP record changed from natural stop to the fixed output All fixed-prefix raw logits were finite, with same-arm A/A exactly equal Ready live allocation and KV were unchanged: 28,605,358,080 allocated bytes, Startup-peak clarification: neither tested #522 snapshot includes the still-open Both full-model captures and sandbox scoring exited successfully. Shutdown For completeness, optional small-shape tuning ON (still 4B/QPN ON) measured AI assistance: Codex executed the regression and prepared this addendum at |
Purpose
Connect the AWQ M=1 operator from #519 to a narrow, default-off runtime route for Qwen3.8 TP4 single-token decode, and record the full-model evidence for it.
Depends on #519 (the operator) and #520 (the layer contract helper and the grouped 2 to 8 token baseline both arms ran on). This branch contains both so it can be built and tested as a whole; the commits specific to this PR are the last two,
4d95867e3e(dispatch) and356c1bafff(acceptance documentation). The rest of the diff disappears once #519 and #520 merge.VLLM_SM70_AWQ_QWEN38_QPN_M1, default0, accepting only0or1.(1, 2560)input, INT32(1, 10)expert IDs, FP32(1, 10)router weights. Every other physical batch shape, including padded CUDA Graph batches, keeps its existing route.0and restart; changing the variable cannot replace an already captured graph.Full-model performance
4x Tesla V100 PCIe 32 GB, TP4/MTP0, FP16 activations and KV, native-group-32 AWQ checkpoint, 4-byte metadata, frozen prompt token IDs, prefix cache off, 8192 max batched tokens,
ignore_eos=false, 320 output tokens, one score per cell and arm. Both arms include #520's grouped-decode route and the same separately tracked QSA page4 fix (#494). Pure aggregate decode tok/s over the common all-active window:C1 gains 18.0% in this pair; the same-day NVFP4 reference on the same contract was 60.26 tok/s, so the remaining gap is about 2.0%. An earlier prototype pair on the same contract measured 51.50 to 59.16 tok/s. C4 and C8 do not take this route except in a one-token drain tail and are unchanged within run-to-run noise.
Per-step GPU service time, averaged over ranks, from the traces of the prototype pair: W13 1.418 to 0.736 ms, W2 including weighted reduction 1.139 to 0.505 ms, the format-specific prepare kernel 0.988 ms to absent; QSA, HC and shared-expert gate unchanged. All 48 layers hit the new W13/W2 kernels; the old prepare and standalone reduce kernels are absent from every graph.
Memory after startup is identical between arms on all four ranks: 563 KV blocks, 5,762,813,952 KV bytes, 28,605,358,080 PyTorch allocated bytes per rank.
Numerical acceptance
Both paths approximate the same fixed AWQ-weight computation and neither is ground truth. Each was compared against the same independently decoded-weight FP64 reference; holding the checkpoint fixed separates this change's arithmetic perturbation from the quantization error present in both.
47/65 output token streams are identical. One GSM8K regression and one IFEval improvement remain and are not netted against each other; this is not a zero-regression or statistical non-inferiority result.
argmaxrather than the first index oftopk(2)at ties; raw tensors and scores did not change.Current evidence supports numerical trajectory variation without a systematic kernel defect on the tested inputs. It does not establish broad quality non-inferiority or production readiness, which is why the route is opt-in.
Duplicate-work check
Open-PR searches on 2026-09-06 in
1CatAI/1Cat-vLLMfor "AWQ QPN", "QPN M1", "awq_qpn", "AWQ M1" and "Qwen3.8 AWQ decode" found no competing AWQ single-token route. #510 tunes the NVFP4 M=1 kernel; #509 is conversion-cache release; #504 is NVFP4 batched work. Base ismain@755baae1d0.Tests
tests/quantization/test_awq_qpn_sm70.py,test_sm70_awq_active_grouped_decode.py,test_sm70_awq_indexed_prefill.py,test_sm70_awq_compact_metadata.py: 69 passed. Covers default-off never touching the native lookup, rejected flag values, unsupported layers failing closed, missing native build failing closed, both metadata layouts, no sidecar loading, single-physical-token admission across 0/1/2/4/5/8/128/8192 tokens, dtype and stride rejection, rollback, and the real MoE branch calling the native op with the existing banks.git diff --check: clean.e5083c1f...8916e1.Provenance
Fork review draft: Leonccaa#12 (same commits, rebased onto #520 plus the same operator change as #519). Design and acceptance notes:
docs/design/sm70_awq_qpn_m1.md.AI assistance was used. OpenAI Codex implemented the dispatch, tests, attribution and evidence under Leon's direction; Claude Code reviewed the diff, re-ran the CPU tests and pre-commit on this branch, and prepared this submission. Human review is still required.
🤖 Generated with Claude Code